
class InputDataStream
{
public:
    InputDataStream();
    ~InputDataStream();
    void FreeMemory();

    //
    // Reads stream from file
    //
    void LoadFromFile(const string &filename, bool expectBufferSizeHeader = false);
    //void LoadFromCompressed(const string &filename);
    void WrapMemory(const vector<BYTE> &stream);

    //
    // Reads data represented by T as binary data from the stream
    //
    template<class type> void ReadData(type &t)
    {
        const UINT byteCount = sizeof(t);
        BYTE *tOffset = (BYTE *)&t;
        const BYTE *streamOffset = _data + _readPtr;
        for(UINT byteIndex = 0; byteIndex < byteCount; byteIndex++)
        {
            *tOffset = *streamOffset;
            streamOffset++;
            tOffset++;
            _readPtr++;
        }
    }

    //
    // Reads raw binary data from the stream
    //
    void ReadData(BYTE *Data, UINT BytesToRead);

    template<class type> void ReadSimpleVector(vector<type> &v)
    {
        UINT length;
        *this >> length;
        v.resize(length);
        if(length > 0)
        {
            ReadData((BYTE *)(&v[0]), length * sizeof(type));
        }
    }

    inline UINT BytesLeft() const
    {
        return _dataLength - _readPtr;
    }

protected:
    UINT _readPtr;
    const BYTE *_data;
    UINT _dataLength;
    vector<BYTE> _storage;
};

//
// Input for several basic types
//

template<class A, class B>
inline InputDataStream& operator >> (InputDataStream &S, pair<A,B> &P)
{
    S >> P.first;
    S >> P.second;
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, BYTE &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, UINT &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, RGBColor &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, int &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, unsigned short &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, float &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, double &A)
{
    S.ReadData(A);
    return S;
}


inline InputDataStream& operator >> (InputDataStream &S, bool &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, UINT64 &A)
{
    S.ReadData(A);
    return S;
}

inline InputDataStream& operator >> (InputDataStream &S, Vec2i &A)
{
    S.ReadData(A);
    return S;
}

template<class type> InputDataStream& operator >> (InputDataStream &S, vector<type> &V)
{
    UINT length;
    S >> length;
    V.resize(length);
    for(UINT index = 0; index < length; index++)
    {
        S >> V[index];
    }
    return S;
}

InputDataStream& operator >> (InputDataStream &S, string &V);